﻿namespace Common.Library
{
    using System;
    using System.Threading.Tasks;

    /// <summary>
    /// 该类封装了异常处理的包装
    /// </summary>
    public class Try
    {
        //private static NLog.ILogger logger = NLog.LogManager.GetLogger("log");

        //private static IDBHelper<ExceptionLog> mongodb = MongodbSource.ExceptionLogger;

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误，如果出现异常，则返回指定类型的默认值</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>         
        /// <typeparam name="TResult">返回结果的类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>   
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <returns>委托的返回结果</returns>
        public static TResult Catch<T1, TResult>(Func<T1, TResult> action, T1 t1, Action<Exception> exceptionHandler = null)
        {
            var tResult = default(TResult);
            try
            {
                tResult = action(t1);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            return tResult;
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误，如果出现异常，则返回指定类型的默认值</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>            
        /// <typeparam name="TResult">返回结果的类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>      
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <returns>委托的返回结果</returns>
        public static TResult Catch<T1, T2, TResult>(Func<T1, T2, TResult> action, T1 t1, T2 t2, Action<Exception> exceptionHandler = null)
        {
            var tResult = default(TResult);
            try
            {
                tResult = action(t1, t2);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            return tResult;
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误，如果出现异常，则返回指定类型的默认值</para>
        /// </summary>        
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>              
        /// <typeparam name="TResult">返回结果的类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>        
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <returns>委托的返回结果</returns>
        public static TResult Catch<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> action, T1 t1, T2 t2, T3 t3, Action<Exception> exceptionHandler = null)
        {
            var tResult = default(TResult);
            try
            {
                tResult = action(t1, t2, t3);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            return tResult;
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误，如果出现异常，则返回指定类型的默认值</para>
        /// </summary>        
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>        
        /// <typeparam name="TResult">返回结果的类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="t4">action的参数4</param>        
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <returns>委托的返回结果</returns>
        public static TResult Catch<T1, T2, T3, T4, TResult>(Func<T1, T2, T3, T4, TResult> action, T1 t1, T2 t2, T3 t3, T4 t4, Action<Exception> exceptionHandler = null)
        {
            var tResult = default(TResult);
            try
            {
                tResult = action(t1, t2, t3, t4);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            return tResult;
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误，如果出现异常，则返回指定类型的默认值</para>
        /// </summary>        
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>
        /// <typeparam name="TResult">返回结果的类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="t4">action的参数4</param>
        /// <param name="t5">action的参数5</param>        
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <returns>委托的返回结果</returns>
        public static TResult Catch<T1, T2, T3, T4, T5, TResult>(Func<T1, T2, T3, T4, T5, TResult> action, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, Action<Exception> exceptionHandler = null)
        {
            var tResult = default(TResult);
            try
            {
                tResult = action(t1, t2, t3, t4, t5);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            return tResult;
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误，如果出现异常，则返回指定类型的默认值</para>
        /// </summary>        
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>        
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <typeparam name="TResult">返回结果的类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="t4">action的参数4</param>
        /// <param name="t5">action的参数5</param>
        /// <param name="t6">action的参数6</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <returns>委托的返回结果</returns>
        public static TResult Catch<T1, T2, T3, T4, T5, T6, TResult>(Func<T1, T2, T3, T4, T5, T6, TResult> action, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, Action<Exception> exceptionHandler = null)
        {
            var tResult = default(TResult);
            try
            {
                tResult = action(t1, t2, t3, t4, t5, t6);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            return tResult;
        }

        /// <summary>
        /// 执行捕捉异常的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <param name="action">要调用的委托</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        public static void Catch(Action action, Action<Exception> exceptionHandler = null)
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T">参数类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t">action的参数</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        public static void Catch<T>(Action<T> action, T t, Action<Exception> exceptionHandler = null)
        {
            try
            {
                action(t);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        public static void Catch<T1, T2>(Action<T1, T2> action, T1 t1, T2 t2, Action<Exception> exceptionHandler = null)
        {
            try
            {
                action(t1, t2);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        public static void Catch<T1, T2, T3>(Action<T1, T2, T3> action, T1 t1, T2 t2, T3 t3, Action<Exception> exceptionHandler = null)
        {
            try
            {
                action(t1, t2, t3);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="t4">action的参数4</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        public static void Catch<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 t1, T2 t2, T3 t3, T4 t4, Action<Exception> exceptionHandler = null)
        {
            try
            {
                action(t1, t2, t3, t4);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>        
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="t4">action的参数4</param>
        /// <param name="t5">action的参数5</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        public static void Catch<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, Action<Exception> exceptionHandler = null)
        {
            try
            {
                action(t1, t2, t3, t4, t5);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行捕捉异常的带参数的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>        
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="action">要调用的委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="t4">action的参数4</param>
        /// <param name="t5">action的参数5</param>
        /// <param name="t6">action的参数6</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        public static void Catch<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> action, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, Action<Exception> exceptionHandler = null)
        {
            try
            {
                action(t1, t2, t3, t4, t5, t6);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行捕捉异常并执行finally的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>        
        /// <param name="action">要调用的方法委托</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <param name="finallyHandler">finally的handle，默认是null</param>
        public static void CatchFinally(Action action, Action<Exception> exceptionHandler = null, Action finallyHandler = null)
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            finally
            {
                finallyHandler?.Invoke();
            }
        }

        /// <summary>
        /// 执行捕捉异常并执行finally的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T">参数类型</typeparam>
        /// <param name="action">要调用的方法委托</param>
        /// <param name="t">参数</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <param name="finallyHandler">finally的handle，默认是null</param>
        public static void CatchFinally<T>(Action<T> action, T t, Action<Exception> exceptionHandler = null, Action finallyHandler = null)
        {
            try
            {
                action(t);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            finally
            {
                finallyHandler?.Invoke();
            }
        }

        /// <summary>
        /// 执行捕捉异常并执行finally的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>                       
        /// <param name="action">要调用的方法委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>           
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <param name="finallyHandler">finally的handle，默认是null</param>
        public static void CatchFinally<T1, T2>(Action<T1, T2> action, T1 t1, T2 t2, Action<Exception> exceptionHandler = null, Action finallyHandler = null)
        {
            try
            {
                action(t1, t2);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            finally
            {
                finallyHandler?.Invoke();
            }
        }

        /// <summary>
        /// 执行捕捉异常并执行finally的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>                    
        /// <param name="action">要调用的方法委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>            
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <param name="finallyHandler">finally的handle，默认是null</param>
        public static void CatchFinally<T1, T2, T3>(Action<T1, T2, T3> action, T1 t1, T2 t2, T3 t3, Action<Exception> exceptionHandler = null, Action finallyHandler = null)
        {
            try
            {
                action(t1, t2, t3);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            finally
            {
                finallyHandler?.Invoke();
            }
        }

        /// <summary>
        /// 执行捕捉异常并执行finally的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>               
        /// <param name="action">要调用的方法委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="t4">action的参数4</param>        
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <param name="finallyHandler">finally的handle，默认是null</param>
        public static void CatchFinally<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 t1, T2 t2, T3 t3, T4 t4, Action<Exception> exceptionHandler = null, Action finallyHandler = null)
        {
            try
            {
                action(t1, t2, t3, t4);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            finally
            {
                finallyHandler?.Invoke();
            }
        }

        /// <summary>
        /// 执行捕捉异常并执行finally的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>                
        /// <param name="action">要调用的方法委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="t4">action的参数4</param>
        /// <param name="t5">action的参数5</param>        
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <param name="finallyHandler">finally的handle，默认是null</param>
        public static void CatchFinally<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, Action<Exception> exceptionHandler = null, Action finallyHandler = null)
        {
            try
            {
                action(t1, t2, t3, t4, t5);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            finally
            {
                finallyHandler?.Invoke();
            }
        }

        /// <summary>
        /// 执行捕捉异常并执行finally的委托
        /// <para>本方法不处理异常，不记录日志也不抛出错误</para>
        /// </summary>
        /// <typeparam name="T1">参数1类型</typeparam>
        /// <typeparam name="T2">参数2类型</typeparam>
        /// <typeparam name="T3">参数3类型</typeparam>
        /// <typeparam name="T4">参数4类型</typeparam>
        /// <typeparam name="T5">参数5类型</typeparam>        
        /// <typeparam name="T6">参数6类型</typeparam>
        /// <param name="action">要调用的方法委托</param>
        /// <param name="t1">action的参数1</param>
        /// <param name="t2">action的参数2</param>
        /// <param name="t3">action的参数3</param>
        /// <param name="t4">action的参数4</param>
        /// <param name="t5">action的参数5</param>
        /// <param name="t6">action的参数6</param>
        /// <param name="exceptionHandler">处理异常的handle，默认是null</param>
        /// <param name="finallyHandler">finally的handle，默认是null</param>
        public static void CatchFinally<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> action, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, Action<Exception> exceptionHandler = null, Action finallyHandler = null)
        {
            try
            {
                action(t1, t2, t3, t4, t5, t6);
            }
            catch (Exception ex)
            {
                exceptionHandler?.Invoke(ex);
            }
            finally
            {
                finallyHandler?.Invoke();
            }
        }

        /// <summary>
        /// 执行捕捉异常并执行finally的委托，该方法将记录日志，并有一个返回值
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <typeparam name="T">返回值的类型</typeparam>
        /// <param name="func">执行的委托</param>        
        /// <param name="message">自定义的异常标题</param>
        /// <param name="finallyHandler">finally的委托</param>
        /// <returns>操作返回的数据</returns>
        public static T ThrowCatchFinallyLog<T>(Func<T> func, string message = "程序出现错误", Action finallyHandler = null)
        {
            try
            {
                return func();
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                throw ex;
            }
            finally
            {
                finallyHandler?.Invoke();
            }
        }

        /// <summary>
        /// 执行一个具有返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>
        public static T CatchLog<T>(Func<T> action, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            T result = default(T);
            try
            {
                result = action();
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
            return result;
        }

        /// <summary>
        /// 执行一个具有返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>        
        /// <typeparam name="TResult">委托返回值的类型</typeparam>
        /// <param name="t1">参数1</param>        
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static TResult CatchLog<T1, TResult>(Func<T1, TResult> action, T1 t1, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            TResult result = default(TResult);
            try
            {
                result = action(t1);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
            return result;
        }

        /// <summary>
        /// 执行一个具有返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>       
        /// <typeparam name="TResult">委托返回值的类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>        
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static TResult CatchLog<T1, T2, TResult>(Func<T1, T2, TResult> action, T1 t1, T2 t2, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            TResult result = default(TResult);
            try
            {
                result = action(t1, t2);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
            return result;
        }

        /// <summary>
        /// 执行一个具有返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>
        /// <typeparam name="T3">参数3的类型</typeparam>           
        /// <typeparam name="TResult">委托返回值的类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>        
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static TResult CatchLog<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> action, T1 t1, T2 t2, T3 t3, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            TResult result = default(TResult);
            try
            {
                result = action(t1, t2, t3);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
            return result;
        }

        /// <summary>
        /// 执行一个具有返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>
        /// <typeparam name="T3">参数3的类型</typeparam>
        /// <typeparam name="T4">参数4的类型</typeparam>        
        /// <typeparam name="TResult">委托返回值的类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>        
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static TResult CatchLog<T1, T2, T3, T4, TResult>(Func<T1, T2, T3, T4, TResult> action, T1 t1, T2 t2, T3 t3, T4 t4, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            TResult result = default(TResult);
            try
            {
                result = action(t1, t2, t3, t4);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
            return result;
        }

        /// <summary>
        /// 执行一个具有返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>
        /// <typeparam name="T3">参数3的类型</typeparam>
        /// <typeparam name="T4">参数4的类型</typeparam>
        /// <typeparam name="T5">参数5的类型</typeparam>
        /// <typeparam name="TResult">委托返回值的类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>    
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static TResult CatchLog<T1, T2, T3, T4, T5, TResult>(Func<T1, T2, T3, T4, T5, TResult> action, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            TResult result = default(TResult);
            try
            {
                result = action(t1, t2, t3, t4, t5);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
            return result;
        }

        /// <summary>
        /// 执行一个具有返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>
        /// <typeparam name="T3">参数3的类型</typeparam>
        /// <typeparam name="T4">参数4的类型</typeparam>
        /// <typeparam name="T5">参数5的类型</typeparam>
        /// <typeparam name="T6">参数6的类型</typeparam>
        /// <typeparam name="TResult">委托返回值的类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <param name="t6">参数6</param>        
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static TResult CatchLog<T1, T2, T3, T4, T5, T6, TResult>(Func<T1, T2, T3, T4, T5, T6, TResult> action, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            TResult result = default(TResult);
            try
            {
                result = action(t1, t2, t3, t4, t5, t6);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
            return result;
        }

        /// <summary>
        /// 执行一个无返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        public static void CatchLog(Action action, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行一个无返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>            
        /// <param name="t1">参数1</param>              
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static void CatchLog<T1>(Action<T1> action, T1 t1, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            try
            {
                action(t1);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行一个无返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>        
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>        
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static void CatchLog<T1, T2>(Action<T1, T2> action, T1 t1, T2 t2,
             Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            try
            {
                action(t1, t2);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行一个无返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>
        /// <typeparam name="T3">参数3的类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static void CatchLog<T1, T2, T3>(Action<T1, T2, T3> action, T1 t1, T2 t2, T3 t3,
             Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            try
            {
                action(t1, t2, t3);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行一个无返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>
        /// <typeparam name="T3">参数3的类型</typeparam>
        /// <typeparam name="T4">参数4的类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>  
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static void CatchLog<T1, T2, T3, T4>(Action<T1, T2, T3, T4> action, T1 t1, T2 t2, T3 t3, T4 t4,
             Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            try
            {
                action(t1, t2, t3, t4);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行一个无返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>
        /// <typeparam name="T3">参数3的类型</typeparam>
        /// <typeparam name="T4">参数4的类型</typeparam>
        /// <typeparam name="T5">参数5的类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>    
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>       
        public static void CatchLog<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> action, T1 t1, T2 t2, T3 t3, T4 t4,
            T5 t5, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            try
            {
                action(t1, t2, t3, t4, t5);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行一个无返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <typeparam name="T1">参数1的类型</typeparam>
        /// <typeparam name="T2">参数2的类型</typeparam>
        /// <typeparam name="T3">参数3的类型</typeparam>
        /// <typeparam name="T4">参数4的类型</typeparam>
        /// <typeparam name="T5">参数5的类型</typeparam>
        /// <typeparam name="T6">参数6的类型</typeparam>
        /// <param name="t1">参数1</param>
        /// <param name="t2">参数2</param>
        /// <param name="t3">参数3</param>
        /// <param name="t4">参数4</param>
        /// <param name="t5">参数5</param>
        /// <param name="t6">参数6</param>        
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>        
        public static void CatchLog<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> action, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            try
            {
                action(t1, t2, t3, t4, t5, t6);
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行一个有返回值的委托，并用try包裹，如果出错，将会记录异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <typeparam name="T">返回数据的类型</typeparam>
        /// <param name="action">要执行的委托</param>
        /// <param name="resoveExceptionFunc">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <returns>执行的委托的返回值，默认是这个泛型的默认值</returns>
        public static T CatchLog<T>(Func<T> action, Func<Exception, T> resoveExceptionFunc = null, string message = "程序出现错误")
        {
            try
            {
                return action();
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                return resoveExceptionFunc == null ? default(T) : resoveExceptionFunc.Invoke(ex);
            }
        }

        /// <summary>
        /// 执行一个无返回值的委托，并用try包裹，如果出现异常，则记录日志，并在finally记录一个指定的日志
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        /// <param name="info">要执行的委托执行完后需要记录的信息，默认是“日志信息”</param>
        public static void TryCatchFinallyLog(Action action, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误", string info = "日志信息")
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
            }
            finally
            {
                LogInfo(info);
            }
        }

        /// <summary>
        /// 执行一个无返回值的委托，并用try包裹，如果出错，将会记录异常，并且在最后抛出异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <param name="action">要执行的委托</param>
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        public static void ThrowCatchLog(Action action, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
                throw ex;
            }
        }

        /// <summary>
        /// 执行一个有回值的委托，并用try包裹，如果出错，将会记录异常，并且在最后抛出异常
        /// <para>本方法将处理异常，作为日志记录，默认采用mongodb，如果mongodb出现异常，则使用NLOG记录在本地，本地的配置请参考NLOG的配置文件</para>
        /// </summary>
        /// <typeparam name="T">返回的类型</typeparam>
        /// <param name="action">要执行的委托</param>
        /// <param name="resoveExceptionAction">自己处理异常的委托</param>
        /// <param name="message">如果出错需要写入的错误描述，默认是“程序出现错误”</param>
        public static T ThrowCatchLog<T>(Func<T> action, Action<Exception> resoveExceptionAction = null, string message = "程序出现错误")
        {
            try
            {
                return action();
            }
            catch (Exception ex)
            {
                LogError(ex, message);
                resoveExceptionAction?.Invoke(ex);
                throw ex;
            }
        }


        /// <summary>
        /// 记录异常日志，默认记录到mongodb，如果mongodb不能访问，则使用NLOG记录到本地，本地的路径请参考NLOG的配置
        /// </summary>
        /// <param name="ex">异常信息</param>
        /// <param name="message">要显示的消息标题</param>
        private static void LogError(Exception ex, string message)
        {
            Task.Run(() =>
            {
                try
                {
                    // 插入日志到数据库
                    //mongodb.InsertData(exlog);
                    if (ex.GetType().Name != "ValidateException")
                    {
                        NLogHelper.LogError(message, ex);
                       
                    }
                    else
                    {
                        NLogHelper.LogWarn(message, ex);
                        //RedisClient.GetExceptionRedisDb().SaveWarnLog(100, message, ex);
                    }
                }
                catch (Exception exp)
                {
                    NLogHelper.LogError(message, exp);
                    //RedisClient.GetExceptionRedisDb().SaveErrorLog(100, message, ex);
                }
            });
        }

        /// <summary>
        /// 记录信息日志
        /// </summary>        
        /// <param name="message">要显示的信息</param>
        private static void LogInfo(string message)
        {
            NLogHelper.LogInfo("记录信息日志", message);
        }
    }
}
